from datetime import datetime, timedelta
from typing import Dict, List, Optional
from sqlalchemy import func, and_

from models import UserStats, RequestRecord, User, CostRecord, db


class UserStatsService:
    """用户统计服务"""
    
    @staticmethod
    def get_or_create_user_stats(user_id: int) -> UserStats:
        """获取或创建用户统计记录"""
        user_stats = UserStats.query.filter_by(user_id=user_id).first()
        if not user_stats:
            user_stats = UserStats(user_id=user_id)
            db.session.add(user_stats)
            db.session.commit()
        return user_stats
    
    @staticmethod
    def get_or_create_user_stats_no_commit(user_id: int) -> UserStats:
        """获取或创建用户统计记录（不自动提交）"""
        user_stats = UserStats.query.filter_by(user_id=user_id).first()
        if not user_stats:
            user_stats = UserStats(user_id=user_id)
            db.session.add(user_stats)
            # 刷新以确保默认值被设置，但不提交
            db.session.flush()
        return user_stats
    
    @staticmethod
    def update_query_stats(user_id: int, model: str, status: str, 
                          input_tokens: int = 0, output_tokens: int = 0, 
                          total_cost: float = 0.0, duration: float = 0.0):
        """更新用户查询统计"""
        user_stats = UserStatsService.get_or_create_user_stats(user_id)
        
        # 直接更新统计数据
        user_stats.total_queries += 1
        if status == 'completed':
            user_stats.successful_queries += 1
        else:
            user_stats.failed_queries += 1
            
        # 更新模型使用统计
        if not user_stats.model_usage:
            user_stats.model_usage = {}
        model_count = user_stats.model_usage.get(model, 0)
        user_stats.model_usage[model] = model_count + 1
        
        # 更新token统计
        user_stats.total_input_tokens += input_tokens
        user_stats.total_output_tokens += output_tokens
        user_stats.total_tokens += input_tokens + output_tokens
        
        # 更新时间统计
        if duration > 0:
            user_stats.total_duration += duration
            user_stats.avg_duration = user_stats.total_duration / user_stats.total_queries
            
        # 更新费用统计
        user_stats.total_cost += total_cost
            
        # 更新最后活动时间
        user_stats.last_query_at = datetime.utcnow()
        user_stats.updated_at = datetime.utcnow()
        
        db.session.commit()
    
    @staticmethod
    def get_user_stats(user_id: int) -> Optional[UserStats]:
        """获取用户统计信息"""
        return UserStats.query.filter_by(user_id=user_id).first()
    
    @staticmethod
    def get_user_stats_summary(user_id: int) -> Dict:
        """获取用户统计摘要"""
        user_stats = UserStatsService.get_user_stats(user_id)
        user = User.query.get(user_id)
        
        if not user_stats:
            # 如果没有统计数据，获取用户的周请求限制
            weekly_limit = user.weekly_request_limit if user else 50
            weekly_used = user.get_weekly_request_count() if user else 0
            
            return {
                'total_queries': 0,
                'successful_queries': 0,
                'failed_queries': 0,
                'success_rate': 0.0,
                'total_input_tokens': 0,
                'total_output_tokens': 0,
                'total_tokens': 0,
                'total_cost': 0.0,
                'avg_duration': 0.0,
                'model_usage': {},
                'last_query_at': None,
                'weekly_requests_limit': weekly_limit,
                'weekly_requests_used': weekly_used
            }
        
        # 获取周请求限制和使用情况
        weekly_limit = user.weekly_request_limit if user else 50
        weekly_used = user.get_weekly_request_count() if user else 0
        
        return {
            'total_queries': user_stats.total_queries,
            'successful_queries': user_stats.successful_queries,
            'failed_queries': user_stats.failed_queries,
            'success_rate': round((user_stats.successful_queries / user_stats.total_queries * 100) if user_stats.total_queries > 0 else 0, 2),
            'total_input_tokens': user_stats.total_input_tokens,
            'total_output_tokens': user_stats.total_output_tokens,
            'total_tokens': user_stats.total_input_tokens + user_stats.total_output_tokens,
            'total_cost': float(user_stats.total_cost),
            'avg_duration': round(user_stats.avg_duration, 2),
            'model_usage': user_stats.model_usage or {},
            'last_query_at': user_stats.last_query_at.isoformat() if user_stats.last_query_at else None,
            'weekly_requests_limit': weekly_limit,
            'weekly_requests_used': weekly_used
        }
    
    @staticmethod
    def get_user_query_history(user_id: int, limit: int = 50, offset: int = 0, 
                              status: str = None, model: str = None) -> List[RequestRecord]:
        """获取用户查询历史"""
        query = db.session.query(RequestRecord).filter_by(user_id=user_id)
        
        if status:
            query = query.filter_by(status=status)
        if model:
            query = query.filter_by(model=model)
        
        return query.order_by(RequestRecord.created_at.desc())\
                   .limit(limit).offset(offset).all()
    
    @staticmethod
    def get_user_daily_stats(user_id: int, days: int = 30) -> List[Dict]:
        """获取用户每日统计数据"""
        end_date = datetime.now().date()
        start_date = end_date - timedelta(days=days-1)
        
        # 查询指定日期范围内的请求记录
        daily_stats = db.session.query(
            func.date(RequestRecord.created_at).label('date'),
            func.count(RequestRecord.id).label('total_queries'),
            func.sum(func.case([(RequestRecord.status == 'completed', 1)], else_=0)).label('successful_queries'),
            func.sum(func.case([(RequestRecord.status == 'failed', 1)], else_=0)).label('failed_queries'),
            func.sum(RequestRecord.input_tokens).label('total_input_tokens'),
            func.sum(RequestRecord.output_tokens).label('total_output_tokens'),
            func.sum(CostRecord.cost).label('total_cost'),
            func.avg(RequestRecord.duration).label('avg_duration')
        ).outerjoin(CostRecord, RequestRecord.id == CostRecord.request_id).filter(
            and_(
                RequestRecord.user_id == user_id,
                func.date(RequestRecord.created_at) >= start_date,
                func.date(RequestRecord.created_at) <= end_date
            )
        ).group_by(func.date(RequestRecord.created_at)).all()
        
        # 转换为字典格式
        result = []
        for stat in daily_stats:
            result.append({
                'date': stat.date.isoformat() if hasattr(stat.date, 'isoformat') else str(stat.date),
                'total_queries': stat.total_queries or 0,
                'successful_queries': stat.successful_queries or 0,
                'failed_queries': stat.failed_queries or 0,
                'success_rate': round((stat.successful_queries / stat.total_queries * 100) if stat.total_queries > 0 else 0, 2),
                'total_input_tokens': stat.total_input_tokens or 0,
                'total_output_tokens': stat.total_output_tokens or 0,
                'total_cost': float(stat.total_cost or 0),
                'avg_duration': round(float(stat.avg_duration or 0), 2)
            })
        
        return result
    
    @staticmethod
    def get_user_model_stats(user_id: int) -> List[Dict]:
        """获取用户模型使用统计"""
        model_stats = db.session.query(
            RequestRecord.model,
            func.count(RequestRecord.id).label('total_queries'),
            func.sum(func.case([(RequestRecord.status == 'completed', 1)], else_=0)).label('successful_queries'),
            func.sum(func.case([(RequestRecord.status == 'failed', 1)], else_=0)).label('failed_queries'),
            func.sum(RequestRecord.input_tokens).label('total_input_tokens'),
            func.sum(RequestRecord.output_tokens).label('total_output_tokens'),
            func.sum(CostRecord.cost).label('total_cost'),
            func.avg(RequestRecord.duration).label('avg_duration')
        ).outerjoin(CostRecord, RequestRecord.id == CostRecord.request_id).filter(
            RequestRecord.user_id == user_id
        ).group_by(RequestRecord.model).all()
        
        result = []
        for stat in model_stats:
            result.append({
                'model': stat.model,
                'total_queries': stat.total_queries or 0,
                'successful_queries': stat.successful_queries or 0,
                'failed_queries': stat.failed_queries or 0,
                'success_rate': round((stat.successful_queries / stat.total_queries * 100) if stat.total_queries > 0 else 0, 2),
                'total_input_tokens': stat.total_input_tokens or 0,
                'total_output_tokens': stat.total_output_tokens or 0,
                'total_cost': float(stat.total_cost or 0),
                'avg_duration': round(float(stat.avg_duration or 0), 2)
            })
        
        return result
    
    @staticmethod
    def get_system_stats() -> Dict:
        """获取系统整体统计"""
        # 总用户数
        total_users = User.query.count()
        
        # 活跃用户数（最近30天有查询的用户）
        thirty_days_ago = datetime.now() - timedelta(days=30)
        active_users = db.session.query(func.count(func.distinct(RequestRecord.user_id)))\
            .filter(RequestRecord.created_at >= thirty_days_ago).scalar()
        
        # 总查询数
        total_queries = db.session.query(RequestRecord).count()
        
        # 成功查询数
        successful_queries = db.session.query(RequestRecord).filter_by(status='completed').count()
        
        # 失败查询数
        failed_queries = db.session.query(RequestRecord).filter_by(status='failed').count()
        
        # 总token数
        token_stats = db.session.query(
            func.sum(RequestRecord.input_tokens).label('total_input_tokens'),
            func.sum(RequestRecord.output_tokens).label('total_output_tokens')
        ).first()
        
        # 总成本
        total_cost = db.session.query(func.sum(CostRecord.cost)).scalar() or 0
        
        # 平均响应时间
        avg_duration = db.session.query(func.avg(RequestRecord.duration)).scalar() or 0
        
        return {
            'total_users': total_users,
            'active_users': active_users or 0,
            'total_queries': total_queries,
            'successful_queries': successful_queries,
            'failed_queries': failed_queries,
            'success_rate': round((successful_queries / total_queries * 100) if total_queries > 0 else 0, 2),
            'total_input_tokens': token_stats.total_input_tokens or 0,
            'total_output_tokens': token_stats.total_output_tokens or 0,
            'total_tokens': (token_stats.total_input_tokens or 0) + (token_stats.total_output_tokens or 0),
            'total_cost': float(total_cost),
            'avg_duration': round(float(avg_duration), 2)
        }
    
    @staticmethod
    def reset_user_stats(user_id: int) -> bool:
        """重置用户统计数据"""
        user_stats = UserStats.query.filter_by(user_id=user_id).first()
        if user_stats:
            db.session.delete(user_stats)
            db.session.commit()
            return True
        return False
    
    @staticmethod
    def export_user_stats(user_id: int) -> Dict:
        """导出用户完整统计数据"""
        user_stats = UserStatsService.get_user_stats_summary(user_id)
        daily_stats = UserStatsService.get_user_daily_stats(user_id, days=90)
        model_stats = UserStatsService.get_user_model_stats(user_id)
        query_history = UserStatsService.get_user_query_history(user_id, limit=1000)
        
        # 转换查询历史为可序列化格式
        history_data = []
        for record in query_history:
            history_data.append({
                'id': record.id,
                'session_id': record.session_id,
                'query': record.query,
                'model': record.model,
                'status': record.status,
                'input_tokens': record.input_tokens,
                'output_tokens': record.output_tokens,
                'total_cost': float(record.cost_record.cost if record.cost_record else 0),
                'duration': float(record.duration or 0),
                'created_at': record.created_at.isoformat(),
                'started_at': record.started_at.isoformat() if record.started_at else None,
                'completed_at': record.completed_at.isoformat() if record.completed_at else None,
                'error_message': record.error_message
            })
        
        return {
            'user_stats': user_stats,
            'daily_stats': daily_stats,
            'model_stats': model_stats,
            'query_history': history_data,
            'export_time': datetime.now().isoformat()
        }